package com.cskaoyan.service.impl;

import com.cskaoyan.bean.bo.AdListBO;
import com.cskaoyan.bean.bo.CouponCreateBO;
import com.cskaoyan.bean.param.BaseParam;
import com.cskaoyan.bean.pojo.*;
import com.cskaoyan.bean.vo.CouponListVO;
import com.cskaoyan.bean.vo.CouponListuserVO;
import com.cskaoyan.bean.vo.WxMyCouponListVO;
import com.cskaoyan.bean.vo.WxMyCouponVO;
import com.cskaoyan.mapper.MarketCartMapper;
import com.cskaoyan.mapper.MarketCouponMapper;
import com.cskaoyan.mapper.MarketCouponUserMapper;
import com.cskaoyan.mapper.MarketGoodsMapper;
import com.cskaoyan.service.CouponService;
import com.cskaoyan.util.RandomCode;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 优惠券管理
 *
 * @author chenxu
 * @since 2022/04/08 09:17
 */
@Service
public class CouponServiceImpl implements CouponService {

    @Autowired
    MarketCouponMapper couponMapper;

    @Autowired
    MarketCouponUserMapper couponUserMapper;

    @Autowired
    MarketCartMapper cartMapper;

    @Autowired
    MarketGoodsMapper goodsMapper;

    /*
     *
     * 查询优惠券信息
     * @param adListBO
     * @return com.cskaoyan.bean.vo.CouponListVO
     * @author chenxu
     * @since 2022/04/07 8:45
     */
    @Override
    public CouponListVO list(AdListBO adListBO) {
        //当前页码
        Integer page = adListBO.getPage();
        //数据量
        Integer limit = adListBO.getLimit();
        //desc\asc
        String desc = adListBO.getOrder();
        //排序列
        String sort = adListBO.getSort();
        //获取查询接收的name
        String name = adListBO.getName();
        Short status = adListBO.getStatus();
        Short type = adListBO.getType();
        //自动拼接
        PageHelper.startPage(page,limit);
        //创建一个example的对象
        MarketCouponExample example = new MarketCouponExample();
        example.setOrderByClause(sort + " "+ desc);
        MarketCouponExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false);
        if (name != null){
            criteria.andNameLike("%"+name+"%");
        }
        if (type != null){
            criteria.andTypeEqualTo(type);
        }
        if (status != null){
            criteria.andStatusEqualTo(status);
        }
        List<MarketCoupon> couponList = couponMapper.selectByExample(example);
        //
        PageInfo<MarketCoupon> pageInfo = new PageInfo<>(couponList);
        //获取页码总数
        int pages = pageInfo.getPages();
        //获取总的数据量
        int total = (int) pageInfo.getTotal();

        //封装到javabean中
        CouponListVO couponListVO = new CouponListVO();

        couponListVO.setLimit(limit);
        couponListVO.setTotal(total);
        couponListVO.setList(couponList);
        couponListVO.setPage(page);
        couponListVO.setPages(pages);

        return couponListVO;
    }

    /*
     *
     *  删除优惠券数据
     * @param id
     * @return void
     * @author chenxu
     * @since 2022/04/07 11:55
     */
    @Override
    public void delete(Integer id) {
        //真删couponMapper.deleteByPrimaryKey(id);
        //假删，数据库依然存在该信息
        MarketCoupon marketCoupon = couponMapper.selectByPrimaryKey(id);
        marketCoupon.setDeleted(true);

        // 需要将所有用户的这张优惠券，从可用设置为下架，status从0变成3，同时逻辑删除
        MarketCouponUserExample example = new MarketCouponUserExample();
        MarketCouponUserExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false).andCouponIdEqualTo(id).andStatusEqualTo((short) 0);
        List<MarketCouponUser> couponUsers = couponUserMapper.selectByExample(example);
        if (couponUsers != null && !couponUsers.isEmpty()) {
            for (MarketCouponUser couponUser : couponUsers) {
                couponUser.setStatus((short) 3);
                couponUser.setUpdateTime(new Date());
                couponUser.setDeleted(true);
                couponUserMapper.updateByPrimaryKeySelective(couponUser);
            }
        }

        //更新修改时间
        marketCoupon.setUpdateTime(new Date());
        couponMapper.updateByPrimaryKeySelective(marketCoupon);
    }
    /*
     *读取优惠券详情
     *
     * @param id
     * @return com.cskaoyan.bean.pojo.MarketCoupon
     * @author chenxu
     * @since 2022/04/08 9:58
     */
    @Override
    public MarketCoupon read(Integer id) {

        MarketCoupon marketCoupon = couponMapper.selectByPrimaryKey(id);
        return marketCoupon;
    }



    @Override
    public CouponListuserVO listuser(AdListBO adListBO) {

        Integer userId = adListBO.getUserId();
        Short status = adListBO.getStatus();

        //自动拼页码和数据量
        PageHelper.startPage(adListBO.getPage(),adListBO.getLimit());
        //创建exmple
        MarketCouponUserExample example = new MarketCouponUserExample();
        //创建条件对象
        MarketCouponUserExample.Criteria criteria = example.createCriteria();
        //添加条件(id)
        criteria.andCouponIdEqualTo(adListBO.getCouponId());
        if (userId != null ){
            criteria.andUserIdEqualTo(userId);
        }
        if (status != null ){
            criteria.andStatusEqualTo(status);
        }
        List<MarketCouponUser> couponUsers = couponUserMapper.selectByExample(example);

        PageInfo<MarketCouponUser> userPageInfo = new PageInfo<>(couponUsers);
        //获取总的数量和总页码数
        int total = (int) userPageInfo.getTotal();
        int pages = userPageInfo.getPages();
        //将获得数据封装到listuseuVO中
        CouponListuserVO listuserVO = new CouponListuserVO();
        listuserVO.setLimit(adListBO.getLimit());
        listuserVO.setList(couponUsers);
        listuserVO.setPage(adListBO.getPage());
        listuserVO.setPages(pages);

        return listuserVO;
    }
    /*
     *修改 优惠券的信息
     *
     * @param marketCoupon
     * @return com.cskaoyan.bean.pojo.MarketCoupon
     * @author chenxu
     * @since 2022/04/07 15:37
     */
    @Override
    public MarketCoupon update(CouponCreateBO couponBo) {

        MarketCoupon marketCoupon = new MarketCoupon(
                couponBo.getId(),couponBo.getName(),couponBo.getDesc(), couponBo.getTag(),
                couponBo.getTotal(), couponBo.getDiscount(), couponBo.getMin(),
                couponBo.getLimit(), couponBo.getType(), couponBo.getStatus(),
                couponBo.getGoodsType(), couponBo.getGoodsValue(), couponBo.getCode(),
                couponBo.getTimeType(), couponBo.getDays(),couponBo.getStartTime(),
                couponBo.getEndTime(), couponBo.getAddTime(), couponBo.getUpdateTime(), couponBo.getDeleted());
        //先判断优惠券是否为兑换码类型  0:通用类型   1注册赠送券    2：兑换码类型
        if ( couponBo.getType() == (short)2 ){
            //随机生成一个八位的兑换码
            String code = RandomCode.generateShortUuid();
            marketCoupon.setCode(code); }
        marketCoupon.setUpdateTime(new Date());
        couponMapper.updateByPrimaryKey(marketCoupon);
        //再查询
        MarketCoupon coupon = couponMapper.selectByPrimaryKey(marketCoupon.getId());
        return coupon;
    }
    /*
     *添加优惠券信息
     *
     * @param marketCoupon
     * @return com.cskaoyan.bean.pojo.MarketCoupon
     * @author chenxu
     * @since 2022/04/07 16:37
     */
    @Override
    public MarketCoupon create(CouponCreateBO couponBo) {
        MarketCoupon marketCoupon = new MarketCoupon(
                null,couponBo.getName(),couponBo.getDesc(), couponBo.getTag(),
                couponBo.getTotal(), couponBo.getDiscount(), couponBo.getMin(),
                couponBo.getLimit(), couponBo.getType(), couponBo.getStatus(),
                couponBo.getGoodsType(), couponBo.getGoodsValue(), couponBo.getCode(),
                couponBo.getTimeType(), couponBo.getDays(),couponBo.getStartTime(),
                couponBo.getEndTime(), couponBo.getAddTime(), couponBo.getUpdateTime(), couponBo.getDeleted()
        );
        //先判断优惠券是否为兑换码类型  0:通用类型   1注册赠送券    2：兑换码类型
        if ( couponBo.getType() == (short)2 ){
            //随机生成一个八位的兑换码
            String code = RandomCode.generateShortUuid();
            marketCoupon.setCode(code);
         }

        marketCoupon.setAddTime(new Date());
        marketCoupon.setUpdateTime(new Date());
        couponMapper.insertSelective(marketCoupon);

        return marketCoupon;
    }

    // 微信：所有优惠券列表 wx/coupon/list（不用登录）
    @Transactional
    @Override
    public CouponListVO queryCouponList(BaseParam param) {
        Integer page = param.getPage();
        Integer limit = param.getLimit();
        // 开启分页
        PageHelper.startPage(page, limit);

        // 更新过期的优惠券status
        updateCouponStatus();

        // 查询条件：按 add_time 降序，未删除，status=0，type = 0（非兑换、非注册赠券）
        MarketCouponExample example = new MarketCouponExample();
        example.setOrderByClause("add_time desc");
        MarketCouponExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false).andStatusEqualTo((short) 0).andTypeEqualTo((short) 0);
        List<MarketCoupon> couponList = couponMapper.selectByExample(example);
        if (couponList == null || couponList.isEmpty()) {
            return new CouponListVO(0, 1, limit, page, couponList);
        }

        // 获取分页信息
        PageInfo<MarketCoupon> pageInfo = new PageInfo<>(couponList);
        long total = pageInfo.getTotal();
        int pages = pageInfo.getPages();
        return new CouponListVO((int) total, pages, limit, page, couponList);
    }

    @Transactional
    @Override
    public void updateCouponStatus() {
        // 查询所有status=0且未删除的优惠券
        MarketCouponExample example = new MarketCouponExample();
        MarketCouponExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false).andStatusEqualTo((short) 0);
        List<MarketCoupon> couponList = couponMapper.selectByExample(example);
        // 如果已过期，更新优惠券的status=1
        if (couponList != null && !couponList.isEmpty()) {
            for (MarketCoupon coupon : couponList) {
                if (coupon != null && coupon.getEndTime() != null && coupon.getEndTime().before(new Date())) {
                    coupon.setStatus((short) 1);
                    coupon.setUpdateTime(new Date());
                    couponMapper.updateByPrimaryKeySelective(coupon);
                }
            }
        }
    }

    @Transactional
    @Override
    public void updateUserCouponStatus(MarketUser user) {
        MarketCouponUserExample example = new MarketCouponUserExample();
        MarketCouponUserExample.Criteria criteria = example.createCriteria();
        criteria.andDeletedEqualTo(false).andStatusEqualTo((short) 0).andUserIdEqualTo(user.getId());
        List<MarketCouponUser> couponUserList = couponUserMapper.selectByExample(example);
        // 如果已过期，更新优惠券的status=2
        if (couponUserList != null && !couponUserList.isEmpty()) {
            for (MarketCouponUser coupon : couponUserList) {
                if (coupon != null && coupon.getEndTime() != null && coupon.getEndTime().before(new Date())) {
                    coupon.setStatus((short) 2);
                    coupon.setUpdateTime(new Date());
                    couponUserMapper.updateByPrimaryKeySelective(coupon);
                }
            }
        }
    }

    @Transactional
    @Override
    public WxMyCouponListVO queryMyCouponList(BaseParam param, short status, MarketUser user) {
        // 获取分页信息
        Integer page = param.getPage();
        Integer limit = param.getLimit();

        // 开启分页
        PageHelper.startPage(page, limit);

        // 更新优惠券状态
        updateCouponStatus();
        updateUserCouponStatus(user);

        // 查找 market_coupon_user 表，找当前用户的所有未删除、对应状态的优惠券
        MarketCouponUserExample userExample = new MarketCouponUserExample();
        userExample.setOrderByClause("add_time desc");
        MarketCouponUserExample.Criteria criteria = userExample.createCriteria();
        criteria.andDeletedEqualTo(false).andStatusEqualTo(status).andUserIdEqualTo(user.getId());
        List<MarketCouponUser> userCouponList = couponUserMapper.selectByExample(userExample);

        if (userCouponList == null || userCouponList.isEmpty()) {
            return new WxMyCouponListVO((long) 0, 1, limit, page, new ArrayList<>());
        }

        List<WxMyCouponVO> list = new ArrayList<>();
        for (MarketCouponUser couponUser : userCouponList) {
            Integer couponId = couponUser.getCouponId();
            MarketCoupon coupon = couponMapper.selectByPrimaryKey(couponId);
            if (coupon == null || coupon.getStatus() != 0 || coupon.getDeleted()) {
                continue;
            }
            WxMyCouponVO couponVO = new WxMyCouponVO(couponUser.getId(), couponId, coupon.getName(),
                    coupon.getDesc(), coupon.getTag(), coupon.getMin(), coupon.getDiscount(),
                    couponUser.getStartTime(), couponUser.getEndTime(), false);
            list.add(couponVO);
        }

        // 获取分页信息
        PageInfo<MarketCouponUser> pageInfo = new PageInfo<>(userCouponList);
        int pages = pageInfo.getPages();
        long total = pageInfo.getTotal();

        return new WxMyCouponListVO(total, pages, limit, page, list);
    }

    @Transactional
    @Override
    public int couponReceive(MarketCouponUser couponUser, MarketUser user) {
        // 先更新过期的优惠券状态
        updateCouponStatus();
        updateUserCouponStatus(user);

        Integer couponId = couponUser.getCouponId();
        if (couponId == null || couponId == 0) {
            return 404;
        }
        // 根据couponId找到对应的优惠券信息，要求状态可用、未过期、未删除、非兑换注册的券（可以直接领取）
        MarketCoupon coupon = couponMapper.selectByPrimaryKey(couponId);
        if (coupon == null || coupon.getStatus() != 0 || coupon.getDeleted() || coupon.getType() != 0) {
            return 404;
        }
        return couponReceiveOrExchange(user, coupon);
    }

    // 用户通过两种方式领取优惠券的通用方式
    private int couponReceiveOrExchange( MarketUser user, MarketCoupon coupon) {
        // 此时优惠券可用，判断用户领取限制数量
        Short limit = coupon.getLimit();
        // 表示限制用户领取数量
        if (limit != 0) {
            MarketCouponUserExample example = new MarketCouponUserExample();
            MarketCouponUserExample.Criteria criteria = example.createCriteria();
            criteria.andDeletedEqualTo(false).andCouponIdEqualTo(coupon.getId()).andUserIdEqualTo(user.getId());
            List<MarketCouponUser> couponUserList = couponUserMapper.selectByExample(example);
            // 已达领取上限
            if (couponUserList != null && couponUserList.size() >= limit) {
                return 740;
            }
        }
        // 用户能够领取，判断是否需要把优惠券的数量减少
        Integer total = coupon.getTotal();
        if (total != 0) {
            // 表示优惠券不是无限量的，领完下架
            total = total - 1;
            if (total <= 0) {
                coupon.setStatus((short) 2);
            }
            coupon.setTotal(total);
            coupon.setUpdateTime(new Date());
            couponMapper.updateByPrimaryKeySelective(coupon);
        }

        // 添加优惠券
        MarketCouponUser couponUser = new MarketCouponUser();
        couponUser.setUserId(user.getId());
        couponUser.setCouponId(coupon.getId());
        couponUser.setStatus((short) 0);
        // 如果优惠券的time_type是0，基于时间领取，需计算有效期；如果是1，直接有有效期
        if (coupon.getTimeType() == 0) {
            Date now = new Date();
            long startTime = now.getTime();
            Short days = coupon.getDays();
            long endTime = startTime + days * 24 * 60 * 60 * 1000;
            Date endDate = new Date(endTime);
            couponUser.setStartTime(now);
            couponUser.setEndTime(endDate);
        }
        if (coupon.getTimeType() == 1) {
            couponUser.setStartTime(coupon.getStartTime());
            couponUser.setEndTime(coupon.getEndTime());
        }
        couponUser.setAddTime(new Date());
        couponUser.setUpdateTime(new Date());
        int insert = couponUserMapper.insertSelective(couponUser);
        if (insert == 1) {
            return 200;
        }
        return 404;
    }

    @Transactional
    @Override
    public int couponExchange(String code, MarketUser user) {
        // 首先更新优惠券过期状态
        updateCouponStatus();
        updateUserCouponStatus(user);

        // 根据兑换码查找优惠券
        // 其它条件：type=2（兑换），status=0（可用），deleted=false
        MarketCouponExample couponExample = new MarketCouponExample();
        MarketCouponExample.Criteria couponCriteria = couponExample.createCriteria();
        couponCriteria.andTypeEqualTo((short) 2).andStatusEqualTo((short) 0).andDeletedEqualTo(false).andCodeEqualTo(code);
        List<MarketCoupon> couponList = couponMapper.selectByExample(couponExample);
        if (couponList == null || couponList.size() != 1) {
            return 742;
        }

        // 此时优惠券可用，且兑换码正确
        MarketCoupon coupon = couponList.get(0);
        return couponReceiveOrExchange(user, coupon);
    }

    @Transactional
    @Override
    public WxMyCouponListVO queryMySelectCouponList(Integer cartId, MarketUser user) {
        // 更新优惠券状态
        updateCouponStatus();
        updateUserCouponStatus(user);

        // 查找 market_coupon_user 表，找当前用户的所有未删除、可使用的优惠券
        MarketCouponUserExample userExample = new MarketCouponUserExample();
        userExample.setOrderByClause("add_time desc");
        MarketCouponUserExample.Criteria criteria = userExample.createCriteria();
        criteria.andDeletedEqualTo(false).andStatusEqualTo((short) 0).andUserIdEqualTo(user.getId());
        List<MarketCouponUser> userCouponList = couponUserMapper.selectByExample(userExample);
        if (userCouponList == null || userCouponList.isEmpty()) {
            return new WxMyCouponListVO((long) 0, 1, 0, 1, new ArrayList<>());
        }
        List<WxMyCouponVO> list = new ArrayList<>();
        for (MarketCouponUser couponUser : userCouponList) {
            Integer couponId = couponUser.getCouponId();
            MarketCoupon coupon = couponMapper.selectByPrimaryKey(couponId);
            if (coupon == null || coupon.getStatus() != 0 || coupon.getDeleted()) {
                continue;
            }
            WxMyCouponVO couponVO = new WxMyCouponVO(couponUser.getId(), couponId, coupon.getName(),
                    coupon.getDesc(), coupon.getTag(), coupon.getMin(), coupon.getDiscount(),
                    couponUser.getStartTime(), couponUser.getEndTime(), false);
            // 根据cartId，判断当前优惠券是否可用
            Boolean couponUseful = checkCouponUseful(coupon, cartId, user);
            couponVO.setAvailable(couponUseful);
            list.add(couponVO);
        }

        // 获取分页信息
        PageInfo<MarketCouponUser> pageInfo = new PageInfo<>(userCouponList);
        int pages = pageInfo.getPages();
        long total = pageInfo.getTotal();

        return new WxMyCouponListVO(total, pages, (int) total, 1, list);

    }

    // 判断当前优惠券是否在购物车可用
    private Boolean checkCouponUseful(MarketCoupon coupon, Integer cartId, MarketUser user) {
        // 不需要购物车信息：最低消费金额为0，goods_type为0（无商品和类目限制）即可用
        double min = coupon.getMin().doubleValue();
        Short goodsType = coupon.getGoodsType();
        if (min == 0 && goodsType == 0) {
            return true;
        }

        // 需要购物车信息：获得购物车list，里面有商品id，能够得到品类id
        // 如果cartId = 0，表示从购物车购买，根据userId，checked，deleted = 1（market_cart表，0表示在购物车里，1表示直接下单）
        // 如果cartId != 0，表示直接购买，根据cartId和userId获取购物车单条记录
        List<MarketCart> cartList;
        if (cartId == 0) {
            MarketCartExample example1 = new MarketCartExample();
            MarketCartExample.Criteria criteria1 = example1.createCriteria();
            criteria1.andUserIdEqualTo(user.getId()).andCheckedEqualTo(true).andDeletedEqualTo(false);
            cartList = cartMapper.selectByExample(example1);
        } else {
            // 直接购买，会生成一条新的购物车记录
            MarketCartExample example2 = new MarketCartExample();
            MarketCartExample.Criteria criteria2 = example2.createCriteria();
            criteria2.andIdEqualTo(cartId).andUserIdEqualTo(user.getId()).andDeletedEqualTo(true);
            cartList = cartMapper.selectByExample(example2);
        }

        if (cartList == null || cartList.isEmpty()) {
            return false;
        }

        // 写符合优惠券使用条件的代码
        // 如果goodsType=0，全商品可用，需判断cartList总金额是否满足最低消费
        if (goodsType == 0) {
            double amount = 0;
            for (MarketCart cart : cartList) {
                amount += cart.getPrice().doubleValue() * cart.getNumber();
            }
            return amount >= min;
        }
        // 如果goodsType=1，类目限制，需判断cartList是否包含goodsValue指定的类目，且对应金额达到min
        if (goodsType == 1) {
            double amount = 0;
            Integer[] categoryValue = coupon.getGoodsValue();
            for (MarketCart cart : cartList) {
                Integer goodsId = cart.getGoodsId();
                // 根据goodsId找到商品信息，包含类目信息
                MarketGoods goods = goodsMapper.selectByPrimaryKey(goodsId);
                if (goods != null && !goods.getDeleted()) {
                    // 找到当前商品的类目id
                    Integer categoryId = goods.getCategoryId();
                    for (Integer category : categoryValue) {
                        // 如果优惠券的goodsValue里面包含该类目id，说明可以使用
                        if (categoryId.equals(category)) {
                            amount += cart.getPrice().doubleValue() * cart.getNumber();
                        }
                    }
                }
            }
            return amount >= min;
        }

        // 如果goodsType=2，商品限制，需判断cartList是否包含goodsValue指定的商品，且对应金额达到min
        if (goodsType == 2) {
            double amount = 0;
            Integer[] goodsValue = coupon.getGoodsValue();
            for (MarketCart cart : cartList) {
                Integer goodsId = cart.getGoodsId();
                for (Integer goods : goodsValue) {
                    if (goods.equals(goodsId)) {
                        amount += cart.getPrice().doubleValue() * cart.getNumber();
                    }
                }
            }
            return amount >= min;
        }

        return false;
    }
}
